「你只要懂水晶,水晶就會幫助你。」
回村後,山姆賣出了所有水晶,瞬間成為村子裡最富有的人。
其他城鎮的寶石商人也聞名而來,想瞧瞧黑森林的樣貌。
「想要我的水晶嗎?去找吧!全部都在黑森林裡!」
從此之後山姆有了另一個名字:「黑森林水晶實價分析師,山大王,山姆」
PS. 這裡是開發 iOS 手機遊戲的系列文,如果還沒看過之前
劇情文章的朋友,歡迎先點這邊回顧唷!
延續昨天的顯示得分文字,我們繼續在遊戲畫面的右上方加上最高得分的文字節點,一樣放在 scoreNode 裡面
labelBest,讓他顯示的文字為 Best: \(bestScore),將標題與分數組合起來顯示let labelBest = self.labelBest
fontColor:設定文字顏色fontSize:設定文字大小fontName:設定字體position:設定位置horizontalAlignmentMode:設定水平對齊方式verticalAlignmentMode:設定垂直對齊方式labelBest 加到 scoreNode 裡bestScore
class GameScene: SKScene {
    ...
    var labelBest: SKLabelNode?
    var bestScore: Int = 0
    
    override func didMove(to view: SKView) {
        ...
        self.labelBest = SKLabelNode(text: "Best: \(bestScore)")
        if let scoreNode = self.scoreNode, let labelScore = self.labelScore, let labelBest = self.labelBest {
            ...
            labelBest.fontColor = UIColor.white
            labelBest.fontSize = CGFloat(24)
            labelBest.fontName = "Copperplate"
            labelBest.position = CGPoint(x: self.size.width - 10, y: 0)
            labelBest.horizontalAlignmentMode = .right
            labelBest.verticalAlignmentMode = .center
            scoreNode.addChild(labelBest)
        }
    }
}
畫面右上方顯示了最高得分文字
Property list 是一種 XML 格式的檔案,可以用來儲存一些設定值,使用 key-value 的方式
我們可以發現專案內有一個 Info.plist 檔案,它紀錄了許多 app 的設定值
為了與原本專案設定做區別,我們額外新增另一個 .plist 檔案來儲存最高分
請先新增一個 setting.plist 檔案
首先點選新增檔案
選擇 Property List -> Next
將檔案命名為 setting,點擊 Create 按鈕,完成 .plist 檔的新增
點擊 setting.plist,按下 + 新增一個新的欄位
Key 取名為 bestScore,Type 設定為 Number,Value 設定為 0
回到程式碼,新增一個結構 (struct),命名為 Setting,內部新增一個參數命名為 bestScore (與剛剛建立的 setting.plist 內容格式一樣)。
讓這個結構是 Codable 的類型,即遵循 Decodable 與 Encodable 協定。
struct Setting: Codable {
    var bestScore: Int
}
在增加分數時,判斷如果目前得分大於最高得分,就將目前得分存進 bestScore,並且改變 labelBest 的文字顯示
class GameScene: SKScene {
    ...
    func addScore(add: Int) {
        self.score += add
        self.labelScore?.text = "Score: \(self.score)"
        if self.score > bestScore {
            self.bestScore = self.score
            self.labelBest?.text = "Best: \(self.bestScore)"
        }
    }
}
接著來寫儲存最高得分的方法,請新增 setBestScore 方法
setting,讓外部帶想要儲存的資料進來Bundle.main.url 取得 setting.plist 的檔案位置PropertyListEncoder().encode 把資料轉成 property listclass GameScene: SKScene {
    ...
    func setBestScore(setting: Setting) {
        if let path = Bundle.main.url(forResource: "setting", withExtension: "plist") {
            do {
                let data = try PropertyListEncoder().encode(setting)
                try data.write(to: path)
            } catch {
                print(error)
            }
        }
    }
}
新增好儲存方法後,就可以在想要的時機點儲存最高分了,我們先設定在怪物與主角碰觸時,存入最高分
setting,bestScore 帶入最高得分setBestScore 方法,並且把 setting 帶入class GameScene: SKScene {
    ...
    func gameStop() {
        ...
        let setting = Setting(bestScore: self.bestScore)
        self.setBestScore(setting: setting)
    }
}
有了儲存方法後,也需要有取得最高得分紀錄的方法,請新增 getBestScore 方法
Bundle.main.path 取得 setting.plist 檔案位置FileManager.default.contents 取得檔案的內容PropertyListDecoder().decode 將 property list 的內容依照 Setting 結構解析出來self.bestScore
class GameScene: SKScene {
    ...
    func getBestScore() {
        if  let path = Bundle.main.path(forResource: "setting", ofType: "plist"),
            let file = FileManager.default.contents(atPath: path),
            let setting = try? PropertyListDecoder().decode(Setting.self, from: file)
        {
            self.bestScore = setting.bestScore
        }
    }
}
在遊戲一開始時,先取得本機內的最高得分紀錄,再接著之前寫的新增文字節點,這樣就可以顯示本機內儲存的分數紀錄了
class GameScene: SKScene {
    ...
    override func didMove(to view: SKView) {
        ...
        self.getBestScore()
        ...
    }
}
可以看到畫面上顯示當前的最高得分,並且在重新開啟遊戲後,還是存有之前的紀錄
參考來源:
Information Property List
Codable
encode(_:)
contents(atPath:)
decode(_:from:)
How To: Working with Plist in Swift